import tkinter as tk
from tkinter import ttk, messagebox
import os
import sys
import stat

class DirectoryTree:
    def __init__(self, parent, initial_path):
        self.parent = parent
        self.initial_path = initial_path
        self.root_node = None
        self.app = None  # 将在main_window中设置，用于与终端通信
        
        # 创建树状视图
        self.tree = ttk.Treeview(parent, show="tree")
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(parent, orient=tk.VERTICAL, command=self.tree.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        # 绑定事件
        self.tree.bind("<Double-1>", self.on_double_click)
        self.tree.bind("<Button-3>", self.on_right_click)  # 右键点击事件
        
        # 创建右键菜单
        self.context_menu = tk.Menu(parent, tearoff=0)
        self.context_menu.add_command(label="转到", command=self.goto_directory_from_menu)
        
        # 当前右键点击的项目
        self.right_clicked_item = None
        
        # 初始化目录树
        self.initialize_tree()
    
    def initialize_tree(self):
        # 获取Windows系统的所有驱动器
        drives = self.get_windows_drives()
        
        # 添加每个驱动器作为顶级节点
        for drive in drives:
            drive_id = self.tree.insert('', tk.END, text=drive, open=False)
            # 对于当前路径所在的驱动器，预先展开
            if self.initial_path.lower().startswith(drive.lower()):
                self.tree.item(drive_id, open=True)
                self.populate_tree(drive_id, drive)
                # 展开当前目录路径
                self.expand_to_path(self.initial_path)
            else:
                # 为其他驱动器添加占位符
                self.tree.insert(drive_id, tk.END, text="", open=False)
    
    def get_windows_drives(self):
        # 获取Windows系统的所有驱动器
        drives = []
        for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
            drive = f"{letter}:\\"
            if os.path.exists(drive):
                drives.append(drive)
        return drives
    
    def populate_tree(self, parent, path):
        # 清空父节点下的所有子节点
        for child in self.tree.get_children(parent):
            self.tree.delete(child)
        
        try:
            # 获取目录下的所有项目
            items = os.listdir(path)
            folders = []
            files = []
            
            # 分离文件夹和文件
            for item in items:
                item_path = os.path.join(path, item)
                if os.path.isdir(item_path):
                    folders.append(item)
                else:
                    files.append(item)
            
            # 先添加文件夹，再添加文件
            for folder in sorted(folders):
                folder_path = os.path.join(path, folder)
                folder_id = self.tree.insert(parent, tk.END, text=folder, open=False)
                # 添加一个占位符，用于触发展开事件
                self.tree.insert(folder_id, tk.END, text="", open=False)
                
            # 添加文件
            for file in sorted(files):
                file_path = os.path.join(path, file)
                # 使用不同的样式来区分文件和文件夹
                file_id = self.tree.insert(parent, tk.END, text=file, open=False)
                
        except PermissionError:
            # 处理没有权限访问的目录
            self.tree.insert(parent, tk.END, text="[无权限访问]", open=False)
        except Exception as e:
            # 处理其他错误
            self.tree.insert(parent, tk.END, text=f"[错误: {str(e)}]", open=False)
    
    def on_double_click(self, event):
        # 获取被点击的项目
        item = self.tree.identify_row(event.y)
        if item:
            # 获取项目路径
            path = self.get_full_path(item)
            if os.path.isdir(path):
                # 如果是目录，检查是否已经展开
                if self.tree.item(item, "open"):
                    # 已经展开，保持原样
                    pass
                else:
                    # 未展开，填充子节点
                    self.populate_tree(item, path)
            else:
                # 如果是文件，检查是否可以通过记事本打开
                file_ext = os.path.splitext(path)[1].lower()
                if file_ext in ['.py', '.txt']:
                    try:
                        # 使用系统默认程序打开文件（在Windows上会用记事本打开txt和py文件）
                        os.startfile(path)
                    except Exception as e:
                        messagebox.showerror("错误", f"无法打开文件: {str(e)}")
    
    def get_full_path(self, item):
        # 递归获取项目的完整路径
        if not item:
            return ""
        
        text = self.tree.item(item, "text")
        parent = self.tree.parent(item)
        
        if not parent:
            # 顶级节点（驱动器）
            return text
        
        # 递归获取父节点的路径
        parent_path = self.get_full_path(parent)
        return os.path.join(parent_path, text)
        
    def on_right_click(self, event):
        # 处理右键点击事件
        item = self.tree.identify_row(event.y)
        if item:
            # 选中被右键点击的项目
            self.tree.selection_set(item)
            self.right_clicked_item = item
            # 显示右键菜单
            self.context_menu.post(event.x_root, event.y_root)
        
    def goto_directory_from_menu(self):
        # 从右键菜单执行目录切换
        if not self.right_clicked_item:
            print("错误: 没有选中的项目")
            return
        
        # 获取选中项目的完整路径
        path = self.get_full_path(self.right_clicked_item)
        print(f"尝试切换到目录: {path}")
        
        if not os.path.exists(path):
            messagebox.showerror("错误", "文件或目录不存在")
            print(f"错误: 路径不存在: {path}")
            return
        
        # 如果是目录，执行切换
        if os.path.isdir(path):
            if self.app:
                print(f"App对象存在")
                if hasattr(self.app, 'change_terminal_directory'):
                    print(f"调用change_terminal_directory方法")
                    self.app.change_terminal_directory(path)
                else:
                    print("错误: App对象没有change_terminal_directory方法")
            else:
                print("错误: App对象不存在")
        

    
    def expand_to_path(self, path):
        # 展开到指定路径
        components = []
        current = path
        
        # 分解路径
        while True:
            current, tail = os.path.split(current)
            if tail:
                components.append(tail)
            else:
                if current:
                    components.append(current)
                break
        
        components.reverse()
        
        # 从根节点开始展开
        current_item = ""
        for component in components:
            # 查找匹配的子节点
            found = False
            for child in self.tree.get_children(current_item):
                if self.tree.item(child, "text") == component:
                    current_item = child
                    self.tree.item(current_item, open=True)
                    # 确保子节点已经被填充
                    path_to_child = self.get_full_path(current_item)
                    self.populate_tree(current_item, path_to_child)
                    found = True
                    break
            
            if not found:
                break